package sever;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.sql.Timestamp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;

public class SeverReaderThread extends Thread{
    private Socket socket;
    public SeverReaderThread(Socket socket)
    {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            // 接收的消息可能有多种类型：1、登录消息（包含昵称）2、群聊消息3、私聊消息
            // 所以客户端必须声明协议发送消息
            // 先从socket管道中接收客户端发送来的消息类型编号
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            while (true) {
                int type = dis.readInt();
                switch (type) {
                    case 1:
                        // 登录消息
                        String nickName = dis.readUTF();
                        // 把这个登录成功的客户端socket存入在线人数列表
                        Sever.onLineSockets.put(socket, nickName);
                        // 更新全部客户端的在线人数列表
                        updateClientOnLineUserList();
                        // 将数据库中存储的聊天记录发送给刚上线的客户端
                        senBDMsgToWin();
                        break;
                    case 2:
                        // 群聊消息
                        String msg = dis.readUTF();
                        sendMsgToAll(msg);
                        // 保存一份到数据库中
                        saveIntoDatabase(msg);
                        break;
                    case 3:
                        // 私聊消息
                        break;
                }
            }
        } catch (Exception e) {
            System.out.println("客户端" + socket.getInetAddress().getHostAddress() + "下线了！");
            // 移除掉下线的客户端
            Sever.onLineSockets.remove(socket);
            // 更新全部客户端的在线人数列表
            updateClientOnLineUserList();
        }
    }

    private void senBDMsgToWin() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DatabaseConnectionPool.dataSource.getConnection();
            String sql = "select * from chat1";
            pstmt = conn.prepareStatement(sql);
            pstmt.executeQuery();
            while (pstmt.getResultSet().next()) {
                Timestamp timestamp = pstmt.getResultSet().getTimestamp("timestamp");
                LocalDateTime localDateTime = timestamp.toLocalDateTime();
                String time = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a"));
                String nickname = pstmt.getResultSet().getString("nickname");
                String msg = pstmt.getResultSet().getString("msg");
                StringBuilder sb = new StringBuilder();
                // 构建消息
                String msgResult = sb.append(nickname).append(" ").append(time).append("\r\n").append(msg).append("\r\n").toString();
                // 发送给刚上线的客户端
                try {
                    DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                    // 群聊消息
                    dos.writeInt(2);
                    dos.writeUTF(msgResult);
                    // 刷新
                    dos.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void saveIntoDatabase(String msg) throws Exception{
        // 获取昵称
        String nickName = Sever.onLineSockets.get(socket);
        // 获取当前时间戳
        LocalDateTime now = LocalDateTime.now();
        // 获取连接池中的连接对象
        Connection conn = DatabaseConnectionPool.dataSource.getConnection();
        try {
            String sql = "insert into chat1(timestamp, nickname, msg) values(?, ?, ?)";
            // 创建PreparedStatement对象,防止SQL注入攻击
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setTimestamp(1, Timestamp.valueOf(now));
            pstmt.setString(2, nickName);
            pstmt.setString(3, msg);
            // 执行更新
            pstmt.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭连接，将连接放回连接池中
            if (conn != null) {
                conn.close();
            }
        }

    }

    private void sendMsgToAll(String msg) {
        StringBuilder sb = new StringBuilder();
        // 获取昵称
        String nickName = Sever.onLineSockets.get(socket);
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
        String nowStr = dtf.format(now);
        String msgResult = sb.append(nickName).append(" ").append(nowStr).append("\r\n").append(msg).append("\r\n").toString();
        for (Socket socket : Sever.onLineSockets.keySet()) {
            try {
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                // 群聊消息
                dos.writeInt(2);
                dos.writeUTF(msgResult);
                // 刷新
                dos.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void updateClientOnLineUserList() {
        Collection<String> onLineUsers = Sever.onLineSockets.values();
        for (Socket socket : Sever.onLineSockets.keySet()) {
            try {
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                // 发送在线人数列表
                dos.writeInt(1);    // 消息类型
                dos.writeInt(onLineUsers.size());
                for (String onLineUser : onLineUsers) {
                    dos.writeUTF(onLineUser);
                }
                // 刷新
                dos.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
